home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-13 / emac16ds.zip / IBM.ASM < prev    next >
Assembly Source File  |  1991-08-14  |  33KB  |  1,554 lines

  1. ;History:1116,1
  2. ;Wed Aug 14 22:47:30 1991 restore the screen to whence it came, not one line lower.
  3. ;Sat May 04 22:20:32 1991 possible bug in pick_init.
  4. ;Sun May 13 23:24:24 1990 Add a "scroll_bar" variable.
  5. ;Mon Mar 26 03:22:48 1990 If they enter e0 using the alt-keypad, pretend it's a real key.
  6. ;Sun Mar 25 13:07:39 1990 Forgot to set num_screen_cols in monochrome mode.
  7. ;Sat Feb 24 20:51:15 1990 M-Escape was M-Esc, which was wrong.
  8. ;Thu Jan 11 23:59:48 1990 Only force video mode 3 if there is no memory at b000:0
  9. ;Wed Oct 11 22:43:28 1989 When inversing, swap the colors rather than xoring with 77h.
  10. ;Sun Sep 24 23:18:42 1989 fix the desqview support.
  11. ;Sun Sep 24 23:05:51 1989 reserve a column on the right for the scroll bar.
  12. ;Tue Sep 19 23:01:46 1989 add Desqview support.
  13. ;Thu Jun 15 23:29:25 1989 Didn't restore port 61h correctly -- crashes a PC.
  14. ;Thu Jun 15 00:27:41 1989 clear_count was destroying dx if ibm_cga != 0.
  15. ;Sun May 28 00:52:17 1989 Use a different method of testing for enhanced keyboards.
  16. ;Sun May 07 00:40:17 1989 Move mouse code from pick.asm to ibm.asm
  17. ;Wed May 03 22:15:40 1989 change the arguments to ring_the_bell.
  18. ;Wed May 03 21:10:32 1989 'and' the background color with 7 to avoid blinking.
  19. ;Tue Mar 07 23:57:47 1989 add parameters to ring_the_bell
  20. ;Tue Mar 07 23:46:52 1989 add Jonathan Vail's visual bell code.
  21. ;Tue Feb 21 22:20:40 1989 add keypad key support.
  22. ;Sat Feb 18 16:57:32 1989 Use hardware cursor positioning for EGA only.
  23. ;Fri Feb 17 22:35:11 1989 cleaned up snow-avoidance code a little.
  24. ;Mon Jan 30 22:58:16 1989 change the parameters for set_screen_color.
  25. ;08-25-88 23:37:09 Create two new keycodes, "C- " and "M- ".
  26. ;05-30-88 22:27:44 fix a small problem in save/restore screen
  27. ;05-29-88 22:49:48 try getting the attributes from lower left.
  28. ;05-29-88 22:42:39 get the attributes from the lower right corner rather than upper right.
  29. ;05-27-88 23:25:34 fix a problem in putch where it put garbage characters up.
  30. ;05-27-88 00:09:00 read_ibm_cga sometimes gets called with ds=bufseg, not data.
  31. ;05-27-88 00:07:02 move_line didn't respect ibm_cga flag--it was always set.
  32. ;05-17-88 20:33:20 Add support for hardware scrolls (should work for all displays) [kdb]
  33. ;05-17-88 20:02:45 Make move_line wait while reading cga screen [kdb]
  34. ;05-17-88 19:35:35 Remove all reference to scrwait function [kdb]
  35. ;05-17-88 19:03:22 Macroize scrwait for single char [kdb]
  36. ;05-15-88 19:16:51 add scrwait in scrolls [kdb]
  37. ;05-15-88 18:58:45 Make move_line wait for each character [kdb]
  38. ;05-07-88 22:07:59 implement a swap_screen_flag.
  39. ;05-03-88 23:54:55 add more extended keys.
  40. ;04-17-88 19:22:28 add some extended keycodes.
  41. ;04-16-88 13:13:01 add extended keyboard support.
  42. ;04-14-88 22:51:58 If ibm_cga, don't store_debug.
  43. ;04-01-88 23:08:28 respond to mouse keys with M-, S-, and C-
  44. ;03-31-88 22:02:25 use C-break for the break character (duh)
  45. ;03-28-88 19:19:14 just clear the screen on a MDA.
  46. ;03-28-88 19:09:19 don't save and restore video memory on an MDA.
  47. ;03-28-88 18:28:50 remove block_cursor and under_cursor
  48. ;03-26-88 21:59:07 change back to bios calls to read the keyboard.
  49. ;03-24-88 00:02:13 add fore_original and back_original.
  50. ;02-21-88 12:24:50 make control be bright, meta inverse video.
  51. ;02-13-88 18:22:56 use the 18.2 ms timer tick to time the beep.
  52. ;02-13-88 16:43:45 don't map Timeout using M-, C-, or S-
  53. ;12-07-87 20:07:29 add store_debug
  54. ;12-05-87 11:23:35 make the color default to the current color.
  55. ;12-05-87 11:20:13 clear the screen on init_entry.
  56. ;12-05-87 11:16:53 save dos's screen and restore it when finished.
  57. ;07-05-87 22:14:22 caps lock shouldn't apply to M- and C- keys.
  58.     page    ,132
  59.  
  60. comment /
  61.  
  62.     Porting EMACS and Percival to MS-DOS computers other than the Z-100:
  63.  
  64. This entire file (Z-100.ASM) needs to be re-written, since it contains
  65. all the Z-100 dependencies.  The following conventions must be maintained:
  66.   1) Never leave this module with DF=1.
  67.   2) Never destroy ES.
  68.   3) Never MOV AX,DATA, always use the copy in the appropriate segment register.
  69.   4) Return NC if a routine succeeds, or fulfills its goals.
  70.  
  71. /
  72.     .xlist
  73.     include    memory.def
  74.  
  75.  
  76. data    segment    byte public
  77.  
  78.     public    max_screen_line
  79. max_screen_line    db    22    ;number of last text row on screen.
  80.  
  81.     public    num_screen_cols
  82. num_screen_cols    db    ?
  83.     db    0            ;in case they access it as a word.
  84.  
  85. screen_columns    db    ?
  86.     db    0            ;in case they access it as a word.
  87.  
  88.     public    fore_original, back_original
  89. fore_original    db    ?
  90. back_original    db    ?
  91.  
  92.  
  93.     public    scan_lines_per_char
  94. scan_lines_per_char    db    8
  95.  
  96.     public    computer_name, computer_name_len
  97. computer_name    db    'IBM-PC'
  98. computer_name_len    equ    $-computer_name
  99.  
  100.     public    swap_screen_flag
  101. swap_screen_flag    dw    1    ;=1 if we should swap screens.
  102.  
  103. old_cursor    dw    ?        ;old cursor position from the swapped
  104.                     ;  screen.
  105.  
  106. mouse_flag    db    ?
  107. mouse_buttons    db    ?
  108.  
  109.  
  110. key_names    label    byte
  111.     db    ',','Comma',0
  112.     db    '(','LPar',0
  113.     db    ')','RPar',0
  114.     db    7fh,'Delete',0
  115.  
  116.     db    -1,'Timeout',0
  117.     db    -2,'Left Down',0        ;mouse button key names.
  118.     db    -3,'Right Down',0
  119.     db    -4,'Left Up',0
  120.     db    -5,'Right Up',0
  121.     db    -6,'Middle Down',0
  122.     db    -7,'Middle Up',0
  123.     db    0
  124.  
  125.  
  126. key_others    label    byte
  127.     db    14,'Back Space',0
  128.     db    15,'Tab',0
  129.     db    28,'Return',0
  130.     db    1,'Escape',0
  131.  
  132.     db    71,'KP7',0        ;Home
  133.     db    72,'KP8',0        ;UpArrow
  134.     db    73,'KP9',0        ;PgUp
  135.     db    74,'KP-',0        ;MMinus
  136.     db    75,'KP4',0        ;LeftArrow
  137.     db    76,'KP5',0        ;Five
  138.     db    77,'KP6',0        ;RightArrow
  139.     db    78,'KP+',0        ;MPlus
  140.     db    79,'KP1',0        ;End
  141.     db    80,'KP2',0        ;DownArrow
  142.     db    81,'KP3',0        ;PgDn
  143.     db    82,'KP0',0        ;Ins
  144.     db    83,'KP.',0        ;Del
  145.  
  146.     db    0
  147.  
  148.  
  149. key_special    label    byte
  150.     db    127,'C-Back Space',0
  151.     db    10,'C-Return',0
  152.     db    0
  153.  
  154. key_table    label    byte
  155. ;    db    0,'000',0
  156.     db    1,'M-Escape',0        ;extended
  157. ;    db    2,'002',0
  158.     db    3,'C-@',0
  159. ;    db    4,'004',0
  160. ;    db    5,'005',0
  161. ;    db    6,'006',0
  162. ;    db    7,'007',0
  163. ;    db    8,'008',0
  164. ;    db    9,'009',0
  165. ;    db    10,'010',0
  166. ;    db    11,'011',0
  167. ;    db    12,'012',0
  168. ;    db    13,'013',0
  169.     db    14,'M-Back Space',0    ;extended
  170.     db    15,'S-Tab',0
  171.     db    16,'M-q',0
  172.     db    17,'M-w',0
  173.     db    18,'M-e',0
  174.     db    19,'M-r',0
  175.     db    20,'M-t',0
  176.     db    21,'M-y',0
  177.     db    22,'M-u',0
  178.     db    23,'M-i',0
  179.     db    24,'M-o',0
  180.     db    25,'M-p',0
  181.     db    26,'M-{',0        ;extended
  182.     db    27,'M-}',0        ;extended
  183.     db    28,'M-Return',0        ;extended
  184. ;    db    29,'029',0
  185.     db    30,'M-a',0
  186.     db    31,'M-s',0
  187.     db    32,'M-d',0
  188.     db    33,'M-f',0
  189.     db    34,'M-g',0
  190.     db    35,'M-h',0
  191.     db    36,'M-j',0
  192.     db    37,'M-k',0
  193.     db    38,'M-l',0
  194.     db    39,'M-;',0        ;extended
  195.     db    40,"M-'",0        ;extended
  196.     db    41,'M-`',0        ;extended
  197. ;    db    42,'042',0
  198.     db    43,'M-\',0        ;extended
  199.     db    44,'M-z',0
  200.     db    45,'M-x',0
  201.     db    46,'M-c',0
  202.     db    47,'M-v',0
  203.     db    48,'M-b',0
  204.     db    49,'M-n',0
  205.     db    50,'M-m',0
  206.     db    51,'M-Comma',0        ;extended
  207.     db    52,'M-.',0        ;extended
  208.     db    53,'M-/',0        ;extended
  209. ;    db    54,'054',0
  210.     db    55,'M-Asterisk',0
  211. ;    db    56,'056',0
  212. ;    db    57,'057',0
  213. ;    db    58,'058',0
  214.     db    59,'F1',0
  215.     db    60,'F2',0
  216.     db    61,'F3',0
  217.     db    62,'F4',0
  218.     db    63,'F5',0
  219.     db    64,'F6',0
  220.     db    65,'F7',0
  221.     db    66,'F8',0
  222.     db    67,'F9',0
  223.     db    68,'F10',0
  224. ;    db    69,'069',0
  225. ;    db    70,'070',0
  226.     db    71,'Home',0
  227.     db    72,'Up Arrow',0
  228.     db    73,'Pg Up',0
  229.     db    74,'M-Minus',0
  230.     db    75,'Left Arrow',0
  231.     db    76,'Five',0
  232.     db    77,'Right Arrow',0
  233.     db    78,'M-Plus',0
  234.     db    79,'End',0
  235.     db    80,'Down Arrow',0
  236.     db    81,'Pg Dn',0
  237.     db    82,'Ins',0
  238.     db    83,'Del',0
  239.     db    84,'S-F1',0
  240.     db    85,'S-F2',0
  241.     db    86,'S-F3',0
  242.     db    87,'S-F4',0
  243.     db    88,'S-F5',0
  244.     db    89,'S-F6',0
  245.     db    90,'S-F7',0
  246.     db    91,'S-F8',0
  247.     db    92,'S-F9',0
  248.     db    93,'S-F10',0
  249.     db    94,'C-F1',0
  250.     db    95,'C-F2',0
  251.     db    96,'C-F3',0
  252.     db    97,'C-F4',0
  253.     db    98,'C-F5',0
  254.     db    99,'C-F6',0
  255.     db    100,'C-F7',0
  256.     db    101,'C-F8',0
  257.     db    102,'C-F9',0
  258.     db    103,'C-F10',0
  259.     db    104,'M-F1',0
  260.     db    105,'M-F2',0
  261.     db    106,'M-F3',0
  262.     db    107,'M-F4',0
  263.     db    108,'M-F5',0
  264.     db    109,'M-F6',0
  265.     db    110,'M-F7',0
  266.     db    111,'M-F8',0
  267.     db    112,'M-F9',0
  268.     db    113,'M-F10',0
  269.     db    114,'C-PrtSc',0
  270.     db    115,'C-Left Arrow',0
  271.     db    116,'C-Right Arrow',0
  272.     db    117,'C-End',0
  273.     db    118,'C-Pg Dn',0
  274.     db    119,'C-Home',0
  275.     db    120,'M-1',0
  276.     db    121,'M-2',0
  277.     db    122,'M-3',0
  278.     db    123,'M-4',0
  279.     db    124,'M-5',0
  280.     db    125,'M-6',0
  281.     db    126,'M-7',0
  282.     db    127,'M-8',0
  283.     db    128,'M-9',0
  284.     db    129,'M-0',0
  285.     db    130,'M--',0
  286.     db    131,'M-=',0
  287.     db    132,'C-Pg Up',0
  288. ;all of the following are extended.
  289.     db    133,'F11',0
  290.     db    134,'F12',0
  291.     db    135,'S-F11',0
  292.     db    136,'S-F12',0
  293.     db    137,'C-F11',0
  294.     db    138,'C-F12',0
  295.     db    139,'M-F11',0
  296.     db    140,'M-F12',0
  297.     db    141,'C-Up Arrow',0
  298.     db    142,'C-Minus',0
  299.     db    143,'C-Five',0
  300.     db    144,'C-Plus',0
  301.     db    145,'C-Down Arrow',0
  302.     db    146,'C-Ins',0
  303.     db    147,'C-Del',0
  304.     db    148,'C-Tab',0
  305.     db    149,'C-Slash',0
  306.     db    150,'C-Asterisk',0
  307.     db    151,'M-Home',0
  308.     db    152,'M-Up Arrow',0
  309.     db    153,'M-Pg Up',0
  310. ;    db    154,'154',0
  311.     db    155,'M-Left Arrow',0
  312. ;    db    156,'156',0
  313.     db    157,'M-Right Arrow',0
  314. ;    db    158,'158',0
  315.     db    159,'M-End',0
  316.     db    160,'M-Down Arrow',0
  317.     db    161,'M-Pg Dn',0
  318.     db    162,'M-Ins',0
  319.     db    163,'M-Del',0
  320.     db    164,'M-Slash',0
  321.     db    165,'M-Tab',0
  322.     db    166,'M-Return',0
  323.     db    167,'C- ',0
  324.     db    168,'M- ',0
  325.  
  326. ;    db    224,'Slash',0
  327. ;    db    224,'Return',0
  328.  
  329.     db    0,'Unknown',0
  330.  
  331.  
  332. one_key_string    db    ?,0
  333. ctrl_key_string    db    'C-'
  334. ctrl_key_char    db    ?,0
  335.  
  336. left_flag    equ    1
  337. right_flag    equ    2
  338. ctrl_flag    equ    4
  339. alt_flag    equ    8
  340. all_flags    equ    left_flag + right_flag + ctrl_flag + alt_flag
  341. shift_flags    db    ?
  342.  
  343. bios_seg    segment at 40h
  344.     org    17h
  345. bios_shifts    db    ?
  346. bios_seg    ends
  347.  
  348.  
  349. key_buffer    label    byte        ;this is where we put the ASCII
  350.     db    26 dup(?)        ;  representation of the key.
  351.  
  352.  
  353.     extrn    inversing: word        ;if we're inverse videoing.
  354.  
  355.     public    color
  356. color        db    0fh        ;xbbbifff bbb=background, ifff=fore.
  357. control_color    db    1fh        ;attributes for control characters.
  358. whitespc_color    db    0fh        ;attributes for whitespace characters.
  359.  
  360. font_8_table    label    byte
  361.     db    007h            ;visi space
  362.     db    004h            ;visi tab
  363.     db    ?            ;del
  364.     db    ?            ;eof
  365.     db    ?            ;visi newline
  366.     db    01ah            ;right arrow
  367.     db    ?            ;random char.
  368.     db    01fh            ;visible newline.
  369.     db    018h            ;up arrow.
  370.     db    019h            ;down arrow.
  371.     db    20h            ;trailing space
  372.  
  373. ibm_cga        db    0        ;=0 if we can write to screen anytime,
  374.                     ;=1 if we should wait for retrace.
  375. have_ega    db    0        ;=0 if we don't have an EGA.
  376. scroll_bar    db    0        ;nonzero if we have a scroll bar.
  377.  
  378. int_16_input    db    0        ;function code for keyboard input
  379. int_16_status    db    1        ;function code for keyboard status
  380.  
  381. in_dv        db    0        ;<>0 if we are running under DesqView.
  382.  
  383. data    ends
  384.  
  385.  
  386. code    segment    byte public
  387.     assume    cs:code, ds:data, es:nothing
  388. ;all of the code in this segment is called with the above assumes.
  389.  
  390. break_flag    db    ?
  391.  
  392. their_1b    dd    ?
  393. our_1b:
  394.     mov    cs:break_flag,1
  395.     iret
  396.  
  397.  
  398.     public    init_entry
  399. init_entry:
  400.     push    es            ;get their C-break.
  401.     mov    ax,351bh
  402.     int    21h
  403.     mov    word ptr their_1b+0,bx
  404.     mov    word ptr their_1b+2,es
  405.     pop    es
  406.  
  407.     push    ds            ;set our C-break.
  408.     mov    ax,cs
  409.     mov    ds,ax
  410.     mov    dx,offset our_1b
  411.     mov    ax,251bh
  412.     int    21h
  413.     pop    ds
  414.  
  415. ;
  416. ;Determine if Desqview is present.
  417. ;
  418.     mov    cx,'DE'
  419.     mov    dx,'SQ'
  420.     mov    ax,2b01h
  421.     int    21h
  422.     cmp    al,0ffh
  423.     je    no_desqview
  424.     inc    in_dv
  425. no_desqview:
  426.  
  427. ;
  428. ;Determine whether or not the BIOS supports extended keyboard functions.
  429. ;
  430.     push    ds
  431.     mov    ax,40h
  432.     mov    ds,ax
  433.     mov    al,ds:[96h]        ;keyboard support byte.
  434.     pop    ds
  435.     test    al,10h
  436.     je    init_entry_0        ;no - they don't have an extended kbd.
  437.  
  438.     mov    int_16_input,10h    ;yes - use extended keyboard function codes.
  439.     mov    int_16_status,11h
  440. init_entry_0:
  441.  
  442. ;
  443. ;Now set the video mode to one that we can use.
  444. ;
  445.     mov    ah,15
  446.     int    10h            ;get video state of the PC
  447.     mov    screen_columns,40
  448.     mov    num_screen_cols,40
  449.     cmp    al,1            ;40 column text mode?
  450.     jbe    init_entry_1        ;Yes, ok.
  451.     mov    screen_columns,80
  452.     mov    num_screen_cols,80
  453.     cmp    al,3            ;Is screen CGA Text?
  454.     jbe    init_entry_1        ;Yes, ok.
  455.     cmp    al,7            ;Is screen MDA?
  456.     je    init_entry_5        ;Yes, ok - but we can't have an EGA.
  457.  
  458. ;
  459. ;Check to make sure there's memory at b800h.  If there isn't, revert to
  460. ;video mode 3.
  461. ;
  462.     push    ds
  463.     mov    ax,0b800h
  464.     mov    ds,ax
  465.     mov    ax,ds:[0]        ;save the original
  466.     not    word ptr ds:[0]        ;try to change the memory.
  467.     not    ax            ;change the original.
  468.     cmp    ax,ds:[0]        ;did they both change?
  469.     pushf
  470.     not    ax            ;restore the original contents.
  471.     mov    ds:[0],ax
  472.     popf
  473.     pop    ds
  474.     je    init_entry_1        ;go if there's memory there.
  475.  
  476.     mov    ax,0*256 + 3        ;use 25x80 color if some strange mode.
  477.     int    10h
  478.  
  479. init_entry_1:
  480.     mov    ax,1200h        ;test for an EGA
  481.     mov    bx,10h
  482.     mov    cx,-1
  483.     int    10h
  484.     cmp    cx,-1
  485.     je    init_entry_2        ;no EGA.
  486.  
  487.     mov    have_ega,1        ;remember that we have an EGA.
  488.  
  489.     push    ds            ;get the max scanlines.
  490.     xor    ax,ax
  491.     mov    ds,ax
  492.     mov    al,ds:[484h]
  493.     mov    ah,ds:[485h]
  494.     mov    cl,ds:[44ah]
  495.     pop    ds
  496.  
  497.     mov    screen_columns,cl    ;remember how wide it is.
  498.     sub    al,2            ;leave room for a status and minibuffer line.
  499.     mov    max_screen_line,al
  500.  
  501. init_entry_2:
  502.     mov    al,screen_columns
  503.     mov    num_screen_cols,al
  504.  
  505.     cmp    swap_screen_flag,0    ;should we swap the screen?
  506.     je    init_entry_4        ;no.
  507.  
  508.     mov    bh,0
  509.     mov    ah,3            ;get cursor position
  510.     int    10h
  511.     mov    old_cursor,dx
  512.  
  513.     mov    dl,max_screen_line    ;copy the page zero to page one.
  514.     add    dl,2
  515.     mov    al,dl
  516. ;    inc    al
  517.     add    al,dl
  518. init_entry_3:
  519.     call    move_line        ;enter with dl=source, al=destination.
  520.     dec    al
  521.     dec    dl
  522.     jns    init_entry_3
  523.  
  524. init_entry_5:
  525.     push    es
  526.     mov    dh,0
  527.     mov    dl,max_screen_line
  528.     add    dl,2
  529.     call    get_video_ptr
  530.     mov    ax,es:[di]        ;get the attributes from the lower left.
  531.     pop    es
  532.     mov    fore_original,ah
  533.     and    fore_original,0fh
  534.     mov    cl,4            ;rotate the background to where we
  535.     shr    ah,cl            ;  want it.
  536.     and    ah,7
  537.     mov    back_original,ah
  538.  
  539. clear_screen:
  540.     mov    dh,0            ;clear the screen.
  541.     mov    dl,max_screen_line
  542.     add    dl,2
  543. clear_screen_1:
  544.     call    clear_to_eol        ;enter with dl=row, dh=column.
  545.     dec    dl
  546.     jns    clear_screen_1
  547. init_entry_4:
  548.     jmp    adjust_for_bar
  549.  
  550.  
  551.     public    uninit_exit
  552. uninit_exit:
  553. ;called when exiting.  May destroy any but seg-regs.
  554.  
  555.     push    ds            ;restore C-break.
  556.     lds    dx,their_1b
  557.     mov    ax,251bh
  558.     int    21h
  559.     pop    ds
  560.  
  561.     cmp    swap_screen_flag,0    ;should we swap the screen?
  562.     jne    uninit_exit_4        ;yes.
  563.     ret                ;no.
  564. uninit_exit_4:
  565.  
  566.     mov    al,screen_columns    ;restore the "correct" size.
  567.     mov    num_screen_cols,al
  568.  
  569.     mov    ah,15
  570.     int    10h            ;get video state of the PC
  571.     cmp    al,7            ;don't restore the memory on an MDA
  572.     je    uninit_exit_1        ;  'cuz it ain't there.
  573.  
  574.     mov    dx,old_cursor
  575.     mov    bh,0
  576.     mov    ah,2            ;set cursor position
  577.     int    10h
  578.  
  579.     mov    al,max_screen_line    ;copy the page one to page zero.
  580.     add    al,2
  581.     mov    dl,al
  582.     add    dl,dl
  583. uninit_exit_3:
  584.     call    move_line        ;enter with dl=source, al=destination.
  585.     dec    dl
  586.     dec    al
  587.     jns    uninit_exit_3
  588.  
  589.     jmp    short adjust_for_bar
  590.  
  591. uninit_exit_1:
  592.     mov    dl,0
  593.     mov    dh,max_screen_line
  594.     add    dh,2
  595.     mov    bh,0
  596.     mov    ah,2            ;set cursor position
  597.     int    10h
  598.  
  599.     call    clear_screen
  600. ;fall through
  601. ;
  602. adjust_for_bar:
  603. ;adjust the num_screen_cols for the scroll bar (if enabled).
  604.  
  605.     cmp    scroll_bar,0        ;have they enabled the scroll bar?
  606.     je    adjust_for_bar_1    ;no.
  607.     dec    num_screen_cols
  608. adjust_for_bar_1:
  609.     ret
  610.  
  611.  
  612. outreg    macro    port,value
  613.     mov    al,port
  614.     out    dx,al
  615.     inc    dx
  616.     mov    al,value
  617.     out    dx,al
  618.     dec    dx
  619.     endm
  620.  
  621.  
  622.   if 0
  623. set_start_addr:
  624. ;given screen_start (the first text line on the screen), scan_row (the first
  625. ;  scan row we're displaying), and bot_window, set the appropriate registers.
  626.  
  627.     mov    dx,03dah        ;wait for vertical retrace.
  628.     cli                ;no interrupts.
  629. set_start_addr_h:
  630.     in    al,dx            ;Wait for horizontal retrace
  631.     test    al,8            ; so will catch vertical
  632.     jz    set_start_addr_h    ; retrace at start.
  633. set_start_addr_v:
  634.     in    al,dx            ;Wait for vertical retrace.
  635.     rcr    al,1
  636.     jc    set_start_addr_v
  637.  
  638.     mov    dx,03d4h
  639.  
  640.     mov    bx,screen_start        ;screen_start is given in terms of
  641.     shr    bx,1            ;  bytes, but we need words.
  642.     outreg    0ch,bh            ;the high byte of the starting address.
  643.     outreg    0dh,bl            ;the low byte of the starting address.
  644.  
  645.     outreg    08h,scan_row        ;Preset row scan.
  646.  
  647.     mov    bx,bot_window
  648.     shl    bh,1            ;put the bit in the right place.
  649.     shl    bh,1
  650.     shl    bh,1
  651.     shl    bh,1
  652.     or    bh,0fh            ;assume that the rest are ones.
  653.  
  654.     outreg    18h,bl            ;set the low byte of line compare.
  655.     outreg    07h,bh            ;set the overflow bits.
  656.  
  657.     sti
  658.  
  659.     ret
  660.   endif
  661.  
  662.  
  663.     public    store_ibm_cga
  664. store_ibm_cga:
  665.     cmp    have_ega,0        ;do we have an EGA?
  666.     jne    store_ibm_cga_1        ;yes - we know better than they do,
  667.     mov    ibm_cga,al        ;  so ignore them.
  668. store_ibm_cga_1:
  669.     ret
  670.  
  671.  
  672.     public    store_scroll_bar
  673. store_scroll_bar:
  674.     mov    scroll_bar,al
  675.     or    al,al            ;are they enabling it?
  676.     mov    al,screen_columns
  677.     je    store_scroll_bar_1    ;no, don't leave room for it.
  678.     dec    al
  679. store_scroll_bar_1:
  680.     mov    num_screen_cols,al
  681.     ret
  682.  
  683.  
  684.     public    store_debug
  685. store_debug:
  686.   if 1
  687.     cmp    ibm_cga,0        ;don't do this on an IBM CGA.
  688.     jne    store_debug_1
  689.     push    ds
  690.     push    es
  691.     push    ax
  692.     mov    ax,data
  693.     mov    ds,ax
  694.     mov    es,ax
  695.     mov    dh,screen_columns
  696.     sub    dh,2
  697.     mov    dl,max_screen_line
  698.     inc    dl
  699.     call    get_video_ptr    ;enter with dl=current row, dh=current column.
  700.                 ;return with es:di->character position.
  701.     pop    ax
  702.     mov    es:[di],al
  703.     mov    es:[di+2],ah
  704.     pop    es
  705.     pop    ds
  706. store_debug_1:
  707.   endif
  708.     ret
  709.  
  710.  
  711. ;this routine should check for a break character.  Return cy if none,
  712. ;  nc if we should break.
  713.     public    check_breakchar
  714. check_breakchar:
  715.     cmp    cs:break_flag,0        ;test the break flag.
  716.     mov    cs:break_flag,0        ;clear the break flag.
  717.     stc
  718.     je    check_breakchar_1
  719.     clc
  720. check_breakchar_1:
  721.     ret
  722.  
  723.  
  724.     public    give_up_slice
  725. give_up_slice:
  726.     cmp    in_dv,0
  727.     je    give_up_slice_1
  728.     push    bx
  729.     push    si
  730.     push    bp
  731.     mov    bx,1000h
  732.     int    15h
  733.     pop    bp
  734.     pop    si
  735.     pop    bx
  736. give_up_slice_1:
  737.     ret
  738.  
  739.  
  740.     public    check_for_key
  741. check_for_key:
  742. ;return zr,ax=0 if no key is waiting.
  743. ;return nz,ax=key if a key is waiting, but don't input the key yet.
  744.     mov    ah,int_16_status    ;check for a key.
  745.     int    16h
  746.     jne    check_for_key_1        ;go if we got a key.
  747.     mov    ax,0            ;return ax=0 if we didn't.
  748. check_for_key_1:
  749.     ret
  750.  
  751.  
  752.     public    get_key_value
  753. get_key_value:
  754. ;exit with ax=keycode.
  755.     mov    ah,int_16_input
  756.     int    16h
  757.     ret
  758.  
  759.  
  760.     public    decode_key
  761. decode_key:
  762. ;enter with ax=key value.
  763. ;exit with si,cx -> the key's name in ASCII.
  764.     mov    di,offset key_buffer
  765.  
  766.     cmp    ax,0f9h            ;one of the mouse buttons?
  767.     jb    decode_key_7
  768.     cmp    ax,0feh
  769.     ja    decode_key_7
  770.  
  771.     push    ax
  772.     push    ds
  773.     mov    ax,bios_seg
  774.     mov    ds,ax
  775.     assume    ds:bios_seg
  776.  
  777.     mov    ah,bios_shifts
  778.     and    ah,all_flags        ;isolate the flags we're interested in.
  779.     pop    ds
  780.     assume    ds:data
  781.     mov    shift_flags,ah
  782.     call    decode_meta
  783.     call    decode_ctrl
  784.     call    decode_shift
  785.     pop    ax
  786.  
  787. decode_key_7:
  788.  
  789.     or    al,al            ;extended function key?
  790.     je    decode_key_5
  791.     cmp    ax,00e0h        ;Did they enter e0 using the keypad?
  792.     je    decode_key_6        ;yes -- it's a real key.
  793.     cmp    al,0e0h
  794.     je    decode_key_5
  795.  
  796.     push    ax            ;now we look for ASCII keys that
  797.     mov    si,offset key_others    ;  have dedicated keys.
  798.     call    decode_search        ;search for the scan code names.
  799.     pop    ax
  800.     jne    decode_key_2        ;go if we found it.
  801.  
  802.     mov    ah,al
  803.     mov    si,offset key_names    ;now search for the ASCII keys that
  804.                     ;  we don't (or can't) represent.
  805.     call    decode_search        ;search for the literal names.
  806.     jne    decode_key_1        ;copy it in.
  807.     mov    al,ah
  808.  
  809.     cmp    al,' '            ;control char?
  810.     jae    decode_key_6        ;no
  811.     add    al,'`'            ;yes - convert into letter.
  812.     mov    ctrl_key_char,al
  813.     mov    si,offset ctrl_key_string
  814.     cmp    al,'z'            ;control character > 'C-z'?
  815.     jbe    decode_key_1        ;no.
  816.     sub    ctrl_key_char,'`'-'@'    ;yes - make it C-[, not C-{
  817.     jmp    short decode_key_1
  818. decode_key_2:
  819.     push    si
  820.     mov    si,offset key_special
  821.     mov    ah,al            ;now see if it's one of the ones we
  822.     call    decode_search        ;  know are special.
  823.     pop    ax
  824.     jne    decode_key_1        ;yes - it is.
  825.     mov    si,ax
  826.     jmp    short decode_key_1
  827. decode_key_6:
  828.     mov    one_key_string,al
  829.     mov    si,offset one_key_string
  830.     jmp    short decode_key_1
  831.  
  832. decode_key_5:
  833.     mov    si,offset key_table    ;search for the extended functions.
  834.     call    decode_search
  835. decode_key_1:
  836.     lodsb                ;copy to the next null.
  837.     stosb
  838.     or    al,al
  839.     jne    decode_key_1
  840.     dec    di            ;don't include the null.
  841.     mov    si,offset key_buffer
  842.     mov    cx,di
  843.     sub    cx,si
  844.     ret
  845.  
  846.  
  847. decode_ctrl:
  848.     test    shift_flags,ctrl_flag
  849.     je    decode_ctrl_1
  850.     mov    ax,'C' + '-'*256
  851.     stosw
  852. decode_ctrl_1:
  853.     ret
  854.  
  855.  
  856. decode_shift:
  857.     test    shift_flags,left_flag + right_flag
  858.     je    decode_shift_1
  859.     mov    ax,'S' + '-'*256
  860.     stosw
  861. decode_shift_1:
  862.     ret
  863.  
  864. decode_meta:
  865.     test    shift_flags,alt_flag
  866.     je    decode_meta_1
  867.     mov    ax,'M' + '-'*256
  868.     stosw
  869. decode_meta_1:
  870.     ret
  871.  
  872.  
  873. decode_search:
  874. ;enter with ah=key to search for, si->table.
  875. ;exit with al=key, nz if found, al=0, zr if not found.
  876.     lodsb
  877.     or    al,al            ;end of table?
  878.     je    decode_search_2        ;yes - try shifted values.
  879.     cmp    al,ah            ;is this the key?
  880.     je    decode_search_2        ;yes.
  881. decode_search_1:
  882.     lodsb                ;skip to the next null.
  883.     or    al,al
  884.     jne    decode_search_1
  885.     jmp    decode_search
  886. decode_search_2:
  887.     or    al,al
  888.     ret
  889.  
  890.  
  891.     public    ring_the_bell
  892. ring_the_bell:
  893. ;enter with bx = first argument, cx = second argument.
  894.     or    cx,cx
  895.     jne    ring_the_bell_1
  896.     mov    cx,1            ;defaults to duration of one.
  897. ring_the_bell_1:
  898.     or    bx,bx            ;negative frequency?
  899.     jl    vbell            ;yes - they must want a visual bell.
  900.  
  901.  
  902. ;Beep procedure count values
  903. ;---------------------------
  904. ;To generate a given freqency note out of the speaker with the Beep procedure
  905. ;on the PC using Channel 2 of the 8253 timer, the channel 2 count register
  906. ;must be loaded with a value such that the 8253 input clock frequency
  907. ;(1.19318 MHz) divided by the count figure equals the audio frequency.
  908. ;enter with bx=count figure for frequency to be generated.
  909. beep:
  910.     push    cx
  911.     mov    cx,1
  912.     call    sleep
  913.     pop    cx
  914.     mov    al,0b6h        ; Channel 2, LSB then MSB, Square Wave, Binary
  915.     out    43h,al        ; Program 8253 command register
  916.     mov    ax,bx        ; Get the frequency to be generated
  917.     out    42h,al        ; Load Channel 2 count register LSB
  918.     mov    al,ah
  919.     out    42h,al        ; Load Channel 2 count register MSB
  920.     in    al,61h        ; Read settings from 8255 PPI I/O Port "PB"
  921.     push    ax        ; Save original settings in AH
  922.     or    al,3        ; Enable Timer Channel 2 & Speaker data
  923.     out    61h,al        ; program the 8255 with new setting-speaker on
  924.     call    sleep        ; Wait for a while.
  925.     pop    ax        ; Get original 8255 Port "PB" settings
  926.     out    61h,al        ; Reset port to original values-speaker off
  927.     ret
  928.  
  929.  
  930. vbell:
  931.     push    cx
  932.     mov    cx,1            ;get syncronized with the timer
  933.     call    sleep
  934.  
  935.     call    reverse
  936.  
  937.     pop    cx            ;now wait that many seconds.
  938.     or    cx,cx            ;if zero duration, just wait one tick.
  939.     jne    vbell_1
  940.     mov    cx,1
  941. vbell_1:
  942.     call    sleep
  943.  
  944. reverse:
  945.     push    di            ; Save es,di
  946.     push    es
  947.     call    get_video_seg
  948.  
  949.     mov    ah,num_screen_cols    ; Calc number of chars
  950.     mov    al,max_screen_line
  951.     add    al,2            ; the entire screen
  952.     mul    ah
  953.     mov    cx,ax
  954.     mov    di,1            ; Offset to start at
  955. rev1:
  956.     mov    al,es:[di]    ; Reverse the foreground/background
  957.     rol    al,1
  958.     rol    al,1
  959.     rol    al,1
  960.     rol    al,1
  961.     and    al,77h
  962.     and    byte ptr es:[di],not 77h
  963.     or    es:[di],al
  964.     add    di,2
  965.     loop    rev1
  966.  
  967.     pop    es
  968.     pop    di
  969.  
  970.     ret
  971.  
  972.  
  973. sleep:
  974. ;pause for cx 18ths.
  975.     push    bx
  976.     push    ds        ; make ds = bios.
  977.     mov    ax,40h
  978.     mov    ds,ax
  979. wait2:
  980.     mov    bx,ds:[6ch]    ; Get the current timer value.
  981. wait1:
  982.     cmp    bx,ds:[6ch]    ; Did the timer value "tick"?
  983.     je    wait1        ; No - keep waiting for a tick.
  984.     loop    wait2        ; LOOP is first executed
  985.     pop    ds
  986.     pop    bx
  987.     ret
  988.  
  989.  
  990. code    ends
  991.  
  992. code    segment    byte public
  993.     assume    cs:code, ds:nothing, es:data, ss:data
  994. ;all of the code in this segment is called with the above assumes.
  995.  
  996.  
  997.     public    read_ibm_cga
  998. read_ibm_cga:
  999.     mov    al,ibm_cga
  1000.     ret
  1001.  
  1002.  
  1003.     public    read_scroll_bar
  1004. read_scroll_bar:
  1005.     mov    al,scroll_bar
  1006.     ret
  1007.  
  1008.  
  1009.     public    position_cursor
  1010. position_cursor:
  1011. ;enter with dh=col (0...80), dl=row (0..max_screen_line)
  1012. ;exit with cursor set to that position.
  1013.     push    bx
  1014.     push    dx
  1015.     push    si
  1016.     push    di
  1017.     push    bp
  1018.  
  1019.     xchg    dh,dl
  1020.     mov    bh,0
  1021.     mov    ah,2            ;set cursor position
  1022.     int    10h
  1023.  
  1024.     pop    bp
  1025.     pop    di
  1026.     pop    si
  1027.     pop    dx
  1028.     pop    bx
  1029.     ret
  1030.  
  1031.  
  1032. crt_status equ  3dah                    ; crt status port
  1033.  
  1034. ;requires dx = crt_status.  Destroys ax.
  1035. retrace_wait    macro
  1036.     local    loop1,loop2
  1037. loop1:
  1038.     in    al,dx
  1039.     shr    al,1            ; display enabled?
  1040.     jc    loop1            ; yes, keep waiting
  1041. loop2:
  1042.     in    al,dx
  1043.     shr    al,1            ; now wait for it to go    off
  1044.     jnc    loop2            ; so can have whole cycle
  1045.     endm
  1046.  
  1047.  
  1048.     public    move_line
  1049. move_line:
  1050. ;enter with dl=source row, al=destination row.
  1051.     push    ax
  1052.     push    bx
  1053.     push    cx
  1054.     push    dx
  1055.     push    si
  1056.     push    di
  1057.     push    bp
  1058.     push    ds
  1059.     push    es
  1060.  
  1061.     push    ax            ;compute the source byte.
  1062.     mov    al,screen_columns
  1063.     mul    dl
  1064.     shl    ax,1
  1065.     mov    si,ax
  1066.     pop    ax
  1067.  
  1068.     mov    ah,screen_columns    ;compute the destination byte.
  1069.     mul    ah
  1070.     shl    ax,1
  1071.     mov    di,ax
  1072.  
  1073.     mov    cx,word ptr num_screen_cols    ;move the line.
  1074.     call    get_video_seg        ;get the video card plane.
  1075.     mov    ds,ax
  1076.     assume    ds:nothing, es:nothing
  1077.  
  1078.     cmp    ibm_cga,0
  1079.     je    move_line_2
  1080.  
  1081.     mov    dx,crt_status        ;load it only once.
  1082. move_line_1:
  1083.     retrace_wait
  1084.     lodsw                ;get our char into bx.
  1085.     mov    bx,ax
  1086.     retrace_wait
  1087.     mov    ax,bx
  1088.     stosw
  1089.     loop    move_line_1
  1090.     jmp    short move_line_3
  1091.  
  1092. move_line_2:
  1093.     rep    movsw
  1094.  
  1095. move_line_3:
  1096.  
  1097.     pop    es
  1098.     pop    ds
  1099.     assume    ds:nothing, es:data
  1100.     pop    bp
  1101.     pop    di
  1102.     pop    si
  1103.     pop    dx
  1104.     pop    cx
  1105.     pop    bx
  1106.     pop    ax
  1107.     ret
  1108.  
  1109.  
  1110.     public    read_chars
  1111. read_chars:
  1112. ;enter with dl=source row, es:di -> destination bytes.
  1113. ;exit with di incremented.
  1114.     assume    ds:nothing, es:nothing
  1115.     push    dx
  1116.  
  1117.     mov    al,screen_columns
  1118.     mul    dl
  1119.     shl    ax,1
  1120.     mov    si,ax
  1121.  
  1122.     push    ds
  1123.  
  1124.     push    es
  1125.     mov    cx,word ptr num_screen_cols    ;read the line.
  1126.     call    get_video_seg        ;get the video card plane.
  1127.     mov    ds,ax
  1128.     pop    es
  1129.     assume    ds:nothing, es:nothing
  1130.  
  1131.     mov    dx,crt_status        ;load it only once.
  1132. read_line_1:
  1133.     retrace_wait
  1134.     lodsw                ;get our char into bx.
  1135.     stosb
  1136.     loop    read_line_1
  1137.     pop    ds
  1138.     pop    dx
  1139.     ret
  1140.  
  1141.     assume    ds:nothing, es:data
  1142.  
  1143.     public    clear_to_eol
  1144. clear_to_eol:
  1145. ;enter with dl=current row, dh=current column.
  1146.     push    bx
  1147.     mov    bl,num_screen_cols
  1148.     call    clear_count
  1149.     pop    bx
  1150.     ret
  1151.  
  1152.  
  1153.     public    clear_count
  1154. clear_count:
  1155. ;enter with dl=current row, dh=current column, bl=column to clear to.
  1156.     push    ax
  1157.     push    bx
  1158.     push    cx
  1159.     push    si
  1160.     push    di
  1161.     push    bp
  1162.     push    es
  1163. clear_count_0:
  1164.     cmp    dh,bl        ;already past it?
  1165.     jae    clear_count_3    ;yes.
  1166.  
  1167.     mov    ah,color
  1168.     mov    al,' '            ;clear to the background color.
  1169.     push    ax
  1170.     call    get_video_ptr
  1171.     assume    ds:nothing, es:nothing
  1172.  
  1173.     mov    cl,bl            ;compute the number of chars to clear.
  1174.     sub    cl,dh
  1175.     mov    ch,0
  1176.  
  1177.     pop    ax
  1178.  
  1179.     cmp    ibm_cga,0        ;slow refresh?
  1180.     je    clear_count_2
  1181.  
  1182.     push    dx
  1183.     mov    bx,ax            ;retrace_wait destroys ax.
  1184.     mov    dx,crt_status        ;load it only once.
  1185. clear_count_1:
  1186.     retrace_wait
  1187.     mov    ax,bx
  1188.     stosw
  1189.     loop    clear_count_1
  1190.     pop    dx
  1191.     jmp    short clear_count_3
  1192.  
  1193. clear_count_2:
  1194.     rep    stosw
  1195.  
  1196. clear_count_3:
  1197.     pop    es
  1198.     assume    ds:nothing, es:data
  1199.     pop    bp
  1200.     pop    di
  1201.     pop    si
  1202.     pop    cx
  1203.     pop    bx
  1204.     pop    ax
  1205.     ret
  1206.  
  1207.  
  1208. get_video_ptr:
  1209. ;enter with dl=current row, dh=current column.
  1210. ;doesn't destroy bx.
  1211. ;return with es:di->character position.
  1212.     mov    al,screen_columns    ;compute the offset of the char.
  1213.     mul    dl
  1214.     add    al,dh
  1215.     adc    ah,0
  1216.     shl    ax,1
  1217.     mov    di,ax
  1218. get_video_seg:
  1219. ;return with es,ax=video segment.
  1220.     xor    ax,ax
  1221.     mov    es,ax
  1222.     mov    ax,0b000h
  1223.     cmp    byte ptr es:[449h],7    ;MDA?
  1224.     je    get_video_seg_1        ;yes - we have the segment already.
  1225.     mov    ax,0b800h        ;no - segment at b800h.
  1226. get_video_seg_1:
  1227.     mov    es,ax
  1228.     mov    ah,0feh            ;let desqview change the segment.
  1229.     int    10h
  1230.     mov    ax,es
  1231.     ret
  1232.  
  1233.  
  1234.     public    xychrout
  1235. xychrout:
  1236. ;enter with dh=col, dl=row, al=character to print, ah=font to print it in.
  1237.     push    ax            ;save everything that we might need.
  1238.     push    bx
  1239.     push    cx
  1240.     push    dx
  1241.     push    di
  1242.     push    si
  1243.     push    es
  1244.     push    ds
  1245.     mov    bx,es
  1246.     mov    ds,bx
  1247.     cmp    dh,screen_columns    ;past the right margin?
  1248.     jae    xychrout_3        ;yes - don't print.
  1249.     cmp    ah,0            ;font zero?
  1250.     jne    xychrout_5        ;no - print specially.
  1251.     mov    ah,color        ;assume no inverse video
  1252.     cmp    al,0ffh            ;print 255 specially
  1253.     je    xychrout_del
  1254.     cmp    al,20h            ;is this a space or so?
  1255.     jb    xychrout_control    ;print control chars specially.
  1256.     jmp    short xychrout_1
  1257. xychrout_del:
  1258.     mov    al,7fh-'@'        ;show bold del.
  1259. xychrout_control:
  1260.     mov    ah,control_color
  1261.     add    al,'@'
  1262.     jmp    short xychrout_1
  1263. xychrout_5:
  1264.     mov    ah,whitespc_color
  1265.     mov    bx,offset font_8_table
  1266.     sub    al,4dh            ;first character in font 8.
  1267.     xlat
  1268. xychrout_1:
  1269.     cmp    inversing,0    ; check    inversion flag
  1270.     je    no_invers    ; skip inversion code
  1271.     mov    cl,4        ; we're    inversing: so exchange
  1272.     rol    ah,cl        ; fore & background color
  1273.     and    ah,7Fh        ; avoid    blinking background
  1274. no_invers:
  1275.     mov    bx,ax            ;save the char in bx.
  1276.     call    get_video_ptr
  1277.     assume    ds:nothing, es:nothing
  1278.     cmp    ibm_cga,0        ;if we have an IBM CGA, we have to wait
  1279.     je    xychrout_4        ;  for retrace, otherwise not.
  1280.     mov    dx,crt_status
  1281.     retrace_wait
  1282. xychrout_4:
  1283.     mov    ax,bx
  1284.     stosw
  1285. xychrout_3:
  1286.     pop    ds
  1287.     pop    es
  1288.     assume    ds:nothing, es:data
  1289.     pop    si
  1290.     pop    di
  1291.     pop    dx
  1292.     pop    cx
  1293.     pop    bx
  1294.     pop    ax
  1295.     ret
  1296.  
  1297.  
  1298.     public    hardware_roll_down
  1299. hardware_roll_down:
  1300. ;exit: if this machine is capable of hardware roll, do it and exit with cy=0,
  1301. ;  otherwise, exit with cy=1.  The hardware roll must leave the last line
  1302. ;  on the screen as the last line.
  1303. ;preserve bx.
  1304.     cmp    ibm_cga,0
  1305.     je    no_roll_down
  1306.  
  1307.     push    bx
  1308.     push    cx
  1309.     push    dx
  1310.     mov    ch,ah
  1311.     mov    cl,0
  1312.     mov    dh,al
  1313.     mov    dl,num_screen_cols
  1314.     dec    dl
  1315.     mov    bh,color
  1316.     mov    ax,701h
  1317.     int    10h
  1318.     pop    dx
  1319.     pop    cx
  1320.     pop    bx
  1321.     clc
  1322.     ret
  1323. no_roll_down:
  1324.     stc
  1325.     ret
  1326.  
  1327.  
  1328.     public    hardware_roll_up
  1329. hardware_roll_up:
  1330. ;exit: if this machine is capable of hardware roll, do it and exit with cy=0,
  1331. ;  otherwise, exit with cy=1.  The hardware roll must leave the last line
  1332. ;  on the screen as the last line.
  1333. ;preserve bx.
  1334.     cmp    ibm_cga,0
  1335.     je    no_roll_up
  1336.  
  1337.     push    bx
  1338.     push    cx
  1339.     push    dx
  1340.     mov    ch,ah
  1341.     mov    cl,0
  1342.     mov    dh,al
  1343.     mov    dl,num_screen_cols
  1344.     dec    dl
  1345.     mov    bh,color
  1346.     mov    ax,601h
  1347.     int    10h
  1348.     pop    dx
  1349.     pop    cx
  1350.     pop    bx
  1351.     clc
  1352.     ret
  1353. no_roll_up:
  1354.     stc
  1355.     ret
  1356.  
  1357.  
  1358.     public    set_screen_color
  1359. set_screen_color:
  1360. ;enter with si -> list of colors (fore, back, control, whitespc)
  1361.     mov    cl,4
  1362.     mov    ah,[si+1]        ;background doesn't change.
  1363.     shl    ah,cl
  1364.     and    ah,70h            ;don't let them set blinking colors.
  1365.     mov    al,[si]            ;compute the normal attributes.
  1366.     or    al,ah
  1367.     mov    color,al
  1368.     mov    al,[si+2]        ;now the control attributes.
  1369.     or    al,ah
  1370.     mov    control_color,al
  1371.     mov    al,[si+3]        ;now the whitespace attributes.
  1372.     or    al,ah
  1373.     mov    whitespc_color,al
  1374.     ret
  1375.  
  1376.  
  1377.     public    pick_init, pick_on, pick_off, check_pick, get_pick_values
  1378. pick_init:
  1379.     call    mouse_exists
  1380.     mov    ax,0
  1381.     int    33h
  1382.     mov    mouse_flag,al        ;remember if the mouse exists.
  1383.     mov    mouse_buttons,bl    ;remember the number of buttons.
  1384.     mov    ax,4            ;move the mouse to the upper right hand.
  1385.     mov    cx,635
  1386.     mov    dx,0
  1387.     int    33h
  1388.     mov    ax,10            ;set text cursor (ignored on Z-100).
  1389.     mov    bx,0            ;software text cursor.
  1390.     mov    cx,77ffh        ;screen mask
  1391.     mov    dx,7700h        ;cursor mask
  1392.     int    33h
  1393.  
  1394.     mov    al,max_screen_line    ;compute the "number of scan lines"
  1395.     add    al,2
  1396.     mul    scan_lines_per_char
  1397.     dec    ax
  1398. ;;; this used to be "dec dx", but that can't be right...
  1399.     mov    dx,ax            ;set the "number of scan lines"
  1400.     mov    cx,0
  1401.     mov    ax,8
  1402.     int    33h
  1403.  
  1404.     mov    al,8            ;we're assuming nine bits per char.
  1405.     mul    screen_columns
  1406.     dec    ax
  1407.     mov    dx,ax            ;set the "number of bit columns"
  1408.     mov    cx,0
  1409.     mov    ax,7
  1410.     int    33h
  1411.  
  1412.     call    check_pick        ;ensure that there are no up or down
  1413.     call    check_pick        ;  events left.
  1414.     call    check_pick
  1415.     call    check_pick
  1416.     call    check_pick
  1417.     call    check_pick
  1418.     ret
  1419.  
  1420.  
  1421. pick_on:
  1422.     call    mouse_exists
  1423.     mov    ax,1
  1424.     int    33h
  1425.     ret
  1426.  
  1427.  
  1428. pick_off:
  1429.     call    mouse_exists
  1430.     mov    ax,1            ;ensure that we work with MOUSEKEY.
  1431.     int    33h
  1432.     mov    ax,2
  1433.     int    33h
  1434.     ret
  1435.  
  1436.  
  1437. check_pick:
  1438. ;return nz and al=pick character.  return zr if no pick.
  1439.     call    mouse_exists
  1440.     push    bx
  1441.     push    cx
  1442.     push    dx
  1443.     cmp    mouse_flag,0        ;inhibit mouse presses if it isn't there.
  1444.     je    check_pick_1
  1445.     mov    ax,5
  1446.     mov    bx,0            ;left button press
  1447.     int    33h
  1448.     mov    ax,0feh
  1449.     or    bx,bx
  1450.     jne    check_pick_1
  1451.     mov    ax,5            ;right button press
  1452.     mov    bx,1
  1453.     int    33h
  1454.     mov    ax,0fdh
  1455.     or    bx,bx
  1456.     jne    check_pick_1
  1457.     mov    ax,6            ;left button release
  1458.     mov    bx,0
  1459.     int    33h
  1460.     mov    ax,0fch
  1461.     or    bx,bx
  1462.     jne    check_pick_1
  1463.     mov    ax,6            ;right button release
  1464.     mov    bx,1
  1465.     int    33h
  1466.     mov    ax,0fbh
  1467.     or    bx,bx
  1468.     jne    check_pick_1
  1469.     cmp    mouse_buttons,2        ;do we have only two buttons?
  1470.     je    check_pick_1        ;yes - no pick.
  1471.     mov    ax,6            ;middle button release
  1472.     mov    bx,2
  1473.     int    33h
  1474.     mov    ax,0f9h
  1475.     or    bx,bx
  1476.     jne    check_pick_1
  1477.     mov    ax,5            ;middle button press
  1478.     mov    bx,2
  1479.     int    33h
  1480.     mov    ax,0fah
  1481.     or    bx,bx
  1482.     jne    check_pick_1
  1483. check_pick_1:
  1484.     pop    dx
  1485.     pop    cx
  1486.     pop    bx
  1487.     ret
  1488.  
  1489. get_pick_values:
  1490.     mov    cx,0
  1491.     mov    dx,0
  1492.     call    mouse_exists
  1493.     mov    ax,3
  1494.     int    33h
  1495.  
  1496.     push    cx            ;save the x value.
  1497.  
  1498.     mov    ax,dx
  1499.     div    scan_lines_per_char
  1500.     mov    ah,0
  1501.     push    ax
  1502.     call    read_linesbefore
  1503.     push    ax
  1504.     call    read_newrow
  1505.     pop    bx
  1506.     sub    bx,ax            ;bx=linesbefore - newrow.
  1507.     pop    dx
  1508.     add    dx,bx            ;add y-value.
  1509.     inc    dx            ;ax= y-value - newrow + linesbefore + 1.
  1510.     pop    ax            ;compute the x-value.
  1511.  
  1512.     push    dx
  1513.  
  1514.     mov    cl,8
  1515.     div    cl
  1516.     mov    ah,0
  1517.     inc    ax
  1518.     push    ax            ;add in firstcolumn.
  1519.     call    read_firstcolumn
  1520.     pop    cx
  1521.     add    cx,ax
  1522.  
  1523.     pop    dx
  1524.  
  1525.     ret
  1526.  
  1527.     extrn    read_firstcolumn: near
  1528.     extrn    read_linesbefore: near
  1529.     extrn    read_newrow: near
  1530.  
  1531.  
  1532. ;this routine returns from the routine that called it if the mouse is not
  1533. ;  installed.
  1534. mouse_exists:
  1535.     push    ds
  1536.     xor    ax,ax
  1537.     mov    ds,ax
  1538.     mov    ax,word ptr ds:[33h*4+2]
  1539.     pop    ds
  1540.     cmp    ax,0            ;any mouse interrupt at all?
  1541.     je    mouse_exists_2        ;no - no mouse.
  1542.     cmp    ax,40h            ;is the mouse interrupt in the bios?
  1543.     jne    mouse_exists_1        ;no - must be a real mouse.
  1544. mouse_exists_2:
  1545.     add    sp,2
  1546.     xor    ax,ax
  1547.     ret
  1548. mouse_exists_1:
  1549.     ret
  1550.  
  1551. code    ends
  1552.  
  1553.     end
  1554.